#include <iostream>
#include <cstdlib>
#include <fstream>
#include "Hero.h"

using namespace std;

Hero::Hero()
{
    //A tapasztali pontokat tartalmazó tömb feltöltése, az minden karakter esetén megegyezik.
    ifstream f;
    f.open("exp.dat");
    if(f.fail())
    {
        cout << "Hianyzik a tapasztalati pontokat tartalmazo exp.dat fajl!" << endl;
        exit(1);
    }
    for(int i=0; i<8; i++)
    {
        f >> level_up[i];
    }
    f.close();
}

//A hős aktuális adatainak a kiírása.
void Hero::WriteStats() const
{
    cout << "Nev: " << GetName() << endl;
    cout << "Kaszt: " << GetClass() << endl;

    cout << "Aktualis szint: " << GetLevel() << endl;
    if(GetLevel() != 8)
    {
        cout << "Aktualis tapasztalati pont: " << GetXP() << endl;
        cout << "A szintlepeshez szukseges tovabbi " << level_up[GetLevel()] - GetXP() << " tapasztalati pont." << endl;
    }

    cout << "Eletero: " << GetHP() << endl;
    cout << "Tamadoero: " << GetAttack() << endl;
    cout << "Pancel: " << GetArmor() << endl;
    cout << "Sebesseg: " << GetSpeed() << endl;

    cout << "A karakter kepessegei: " << endl;
    for(int i=0; i<4; i++)
    {
        cout << i+1 << ". " << char_skillnames[i] << ", melynek sebzese " << char_skillmultiply[i]*char_attackpoints[GetLevel()-1] << endl;
    }
    cout << "******************************************************************************" << endl;
}

//Ha a karakter szintet lépett, be kell állítani az új tulajdonságait.
void Hero::LevelUp()
{
    //Kiválasztással megkeressük, hogy melyik az első olyan tapasztalati pontmennyiség, ami kevesebb, mint a karakter tapasztalati pontja.
    int next = 0;
    while((next < 8) && (level_up[next] <= char_xp))
    {
        next ++;
    }

    //Ha találtunk egy olyan szintet, amelyhez elegendő tapasztalati pontja van, de nem azon a szinten áll, akkor megnöveljül
    //a szintjét, ha még nem maximális szintű.
    //Ha még nem maximális szintű, de a tapasztalati pontjai alapján annak kéne lennie, akkor is megnöveljük a karakter szintjét.
    if((next != 8 && next != char_level) || (next == 8 && char_level != 8))
    {
        char_level = next;
        char_hp = char_maxhealthpoints[char_level-1];
        cout << "******************************************************************************" << endl;
        cout << "Szintet leptel! A karaktered szintje mostmar: " << char_level << endl;
        cout << "******************************************************************************" << endl;
    }
}

//A karakter tapasztalati pontjainak a megnövelése egy küldetés után.
void Hero::IncreaseXP(int xp)
{
    if(xp != 0) //be-, vagy átvezető szövegért nem jár tapasztalati pont.
    {
        cout << "A kuldetes teljesitesevel kaptal " << xp << " tapasztalati pontot." << endl;
        cout << "******************************************************************************" << endl;
    }
    char_xp += xp;
}

//Egy karakter létrehozása.
void Hero::CreateChar()
{
    //Név választása.
    cout << "Add meg a karaktered nevet!" << endl;
    cout << "Ekezetes karaktereket ne hasznalj!" << endl;
    cin >> char_name;
    cout << endl;

    //A kasztok tulajdonságai:
    cout << "Kaszt valasztasahoz usd le a neve mellett szereplo szamot!" << endl;
    cout << endl;
    cout << "A valaszthato kasztok:" << endl;
    cout << endl;
    cout << "1. Harcos" << endl;
    cout << "Mithrilbol keszult pancel, amin ember altal keszitett kard nem hatol at." << endl;
    cout << "Arthas, a hodito kardja." << endl;
    cout << "Eros pancelzatu, de lassu kaszt." << endl;
    cout << endl;
    cout << "2. Pap" << endl;
    cout << "Riverwoodi szerzetesek altal keszitett ruha." << endl;
    cout << "Gabriel pengeje." << endl;
    cout << "Gyors mozgas, gyenge pancelzat." << endl;
    cout << endl;
    cout << "3. Varazslo" << endl;
    cout << "Winterholdban szott varazskopeny." << endl;
    cout << "Merlin palcaja." << endl;
    cout << "Nagy sebzes, gyenge pancelzat." << endl;
    cout << endl;

    class_chosen = IsNumber(">>> "); //Ellenőrzés, hogy 1 és 3 között adott-e meg számot.

    switch(class_chosen)
    {
    case 1:
        LoadClass("warrior.dat");
        break;
    case 2:
        LoadClass("priest.dat");
        break;
    case 3:
        LoadClass("mage.dat");
        break;
    }

    //A karakter kezdeti értékeinek a beállításai.
    char_xp = 0;
    char_level = 1;
    char_hp = char_maxhealthpoints[0];
    currentQ = 0;
}

//Egy kaszt tulajdonságainak beolvasása fájlból.
void Hero::LoadClass(string fname)
{
    ifstream f;
    f.open(fname.c_str());

    if(f.fail())
    {
        cout << "Hianyzik a " << fname << " fajl." << endl;
    }

    //Támadási módok
    for(int i=0; i<4; i++)
    {
        getline(f, char_skillnames[i]);
    }

    //Szintenkénti maximális életerők
    for(int i=0; i<8; i++)
    {
        f >> char_maxhealthpoints[i];
    }

    //Szintenkénti támadóerők
    for(int i=0; i<8; i++)
    {
        f >> char_attackpoints[i];
    }

    //Szintenkénti páncél
    for(int i=0; i<8; i++)
    {
        f >> char_armorpoints[i];
    }

    //Szintenkénti sebesség
    for(int i=0; i<8; i++)
    {
        f >> char_speedpoints[i];
    }

    //A támadási módok szorzói
    for(int i=0; i<4; i++)
    {
        f >> char_skillmultiply[i];
    }

    if(f.fail())
    {
        cout << "Hibas a " << fname << " fajl." << endl;
        f.close();
    }
    f.close();
}

//Egy elmentett karakter adatainak betöltése fájlból, ami paraméterül megkapja a karakter nevét.
void Hero::LoadCharacter(string fname)
{
    ifstream f;
    fname += ".sav";
    f.open(fname.c_str());

    if(f.fail())
    {
        cout << "Nincs ilyen nevu karakterhez tartozo mentett allas." << endl;
        exit(1);
    }

    //Az adatok betöltése
    f >> char_name;
    f >> class_chosen;
    f >> char_xp;
    f >> char_hp;
    f >> currentQ;
    f.close();

    if(f.fail())
    {
        cout << "Hibas a mentett allast tartalmazo fajl!" << endl;
        exit(1);
    }

    //Melyik kaszt tulajdonságait kell betöltenie a programnak.
    //A LevelUp() függvénnyel a karakter szintjéhez igazítjuk annak tulajdonságait.
    switch(class_chosen)
    {
    case 1:
        LoadClass("warrior.dat");
        LevelUp();
        break;
    case 2:
        LoadClass("priest.dat");
        LevelUp();
        break;
    case 3:
        LoadClass("mage.dat");
        LevelUp();
        break;
    }
}

//A karakter állásának elmentése.
void Hero::SaveCharacter()
{
    string fname;
    fname = char_name;
    fname += ".sav"; //olyan formátumot adunk meg, amit a felhasználó nem tud megnyitni, és szerkeszteni olyan könnyen
    ofstream f; //létrehozunk egy output fstream-et, amibe történik a mentés

    f.open(fname.c_str());
    if(f.fail())
    {
        cout << "******************************************************************************" << endl;
        cout << "A mentes kozben hiba lepett fel." << endl;
        cout << "******************************************************************************" << endl;
    }

    f << char_name << endl;
    f << class_chosen << endl;
    f << char_xp << endl;
    f << char_hp << endl;
    f << currentQ << endl;
    f.close();

    cout << "******************************************************************************" << endl;
    cout << "A karaketer sikeresen mentesre kerult!" << endl;
    cout << "******************************************************************************" << endl;
}

void Hero::SetQNumber(int number)
{
    currentQ = number;
}

void Hero::SetHP(int amount)
{
    char_hp = amount;
}

int Hero::IsNumber(string text)
{
    int number;
    bool wrong;
    string t;
    do
    {
        cout << text;
        cin >> number;
        wrong = cin.fail();
        if(cin.fail() || number < 1 || number > 3)
        {
            cout << "Kerlek egy egesz szamot irj be 1 es 3 kozott!" << endl;
            cin.clear();
        }
        getline(cin, t);
    }
    while(wrong);
    return number;
}
